home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / t3dlib / source / readlwob.c < prev    next >
C/C++ Source or Header  |  1995-02-13  |  19KB  |  694 lines

  1. /* readlwob.c - read a LightWave3D object file into the internal database
  2.  *            - written by Glenn M. Lewis - 8/7/92
  3.  */
  4.  
  5. static char rcs_id[] = "$Id: readlwob.c,v 1.7 1993/02/14 07:27:06 glewis Exp $";
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "t3dlib.h"
  10. #ifdef __STDC__
  11. #include <stdlib.h>
  12. #include <strings.h>
  13. #include "readlwob_protos.h"
  14. #endif
  15. #define MAXLINE 132
  16.  
  17. extern int verbose_flag;
  18.  
  19. static void process_DESC();
  20. static OBJECT *process_EXTR();
  21. static void process_INFO();
  22. static void process_OBJ();
  23.  
  24. /* Here are a few necessary utilities */
  25.  
  26. static void get_name(name, size, world)
  27. register char  *name;
  28. register int size;
  29. WORLD *world;
  30. {
  31.     while (size--) *name++ = fgetc(world->inp);
  32.     *name = '\0';
  33. }
  34.  
  35. static BYTE get_BYTE(world)
  36. WORLD *world;
  37. {
  38.     return((BYTE)fgetc(world->inp));
  39. }
  40.  
  41. static UBYTE get_UBYTE(world)
  42. WORLD *world;
  43. {
  44.     return((UBYTE)fgetc(world->inp));
  45. }
  46.  
  47. static WORD get_WORD(world)
  48. WORLD *world;
  49. {
  50.     WORD tmp = (WORD)get_UBYTE(world)<<8;
  51.     return((WORD)(tmp|get_UBYTE(world)));
  52. }
  53.  
  54. static UWORD get_UWORD(world)
  55. WORLD *world;
  56. {
  57.     UWORD tmp = (UWORD)get_UBYTE(world)<<8;
  58.     return((UWORD)(tmp|get_UBYTE(world)));
  59. }
  60.  
  61. static ULONG get_ULONG(world)
  62. WORLD *world;
  63. {
  64.     ULONG tmp = (ULONG)get_UWORD(world)<<16;
  65.     return(tmp|get_UWORD(world));
  66. }
  67.  
  68. static double get_FRACT(world)    /* This sets the precision to 10^(-3) */
  69. WORLD *world;
  70. {
  71.     register double whole, fract;
  72.  
  73.     whole =  (double)get_WORD(world);
  74.     fract = ((double)get_UWORD(world))/65536.0;
  75.     return((double)(whole+fract));
  76. }
  77.  
  78. static void stuff_XYZ(st, world)
  79. XYZ_st *st;
  80. WORLD *world;
  81. {
  82.     st->x = get_FRACT(world);
  83.     st->y = get_FRACT(world);
  84.     st->z = get_FRACT(world);
  85. }
  86.  
  87. static void stuff_RGB(st, world)
  88. RGB_st *st;
  89. WORLD *world;
  90. {
  91.     st->r = get_UBYTE(world);
  92.     st->g = get_UBYTE(world);
  93.     st->b = get_UBYTE(world);
  94. }
  95.  
  96. static void output_warning(world, area, name, size)
  97. WORLD *world;
  98. char *area, *name;
  99. ULONG size;
  100. {
  101.     ULONG i;
  102.     int j;
  103.     unsigned char tmpstr[20];
  104.  
  105.     fprintf(stderr, "WARNING: Unknown %ssub-chunk: '%s', size %lu...\n",
  106.         area, name, size);
  107.     for (i=0; i<size; i+=16) {
  108.         fprintf(stderr, "%04lx:", i);
  109.         for (j=0; j<16 && i+j<size; j++)
  110.             fprintf(stderr, " %02x", tmpstr[j] = (fgetc(world->inp)&0xff));
  111.         while (j++ < 16) fputs("   ", stderr);
  112.         fputs("    ", stderr);
  113.         /* Print out the ASCII equivalent */
  114.         for (j=0; j<16 && i+j<size; j++) {
  115.             tmpstr[j] &= 0x7F;   /* Strip off upper bit */
  116.             if (isprint(tmpstr[j]))
  117.                 fputc(tmpstr[j], stderr);
  118.             else fputc('.', stderr);
  119.         }
  120.         fputs("\n", stderr);
  121.     }
  122. }
  123.  
  124. /********************/
  125. /* The MAIN section */
  126. /********************/
  127.  
  128. extern int already_read_header;
  129. extern unsigned char header_storage[13];
  130.  
  131. WORLD *read_LWOB(file)
  132. FILE *file;
  133. {
  134.     register ULONG i, len, size;
  135.     WORLD *world;
  136.     char name[5];
  137.  
  138.     if (!file) return(0L);    /* File not open */
  139.  
  140.     if (!(world = (WORLD*)malloc(sizeof(WORLD)))) { OUT_MEM("WORLD"); }
  141.     bzero((char*)world, sizeof(WORLD));
  142.     world->inp = file;
  143.  
  144.     if (!already_read_header) {
  145.         /* Parse the IFF TDDD file */
  146.         get_name(name, 4, world);
  147.         if (strcmp(name, "FORM") != 0) {
  148.             fprintf(stderr, "ERROR: Input is not an IFF file.\n"); exit(-1); }
  149.         if (!(len = get_ULONG(world))) {
  150.             fprintf(stderr, "ERROR: Bad FORM length in IFF file.\n"); exit(-1); }
  151.         get_name(name, 4, world);
  152.         if (strcmp(name, "LWOB") != 0) {
  153.             fprintf(stderr, "ERROR: IFF file is not a LWOB file.\n"); exit(-1); }
  154.     } else {
  155.         len =    (header_storage[4]<<24) | (header_storage[5]<<16) |
  156.                 (header_storage[6]<< 8) | (header_storage[7]    );
  157.         already_read_header = 0;
  158.     }
  159.     len -= 4;
  160.  
  161. /* Here is the main loop: */
  162.     while (len>0) {
  163.         get_name(name, 4, world);
  164.         size = get_ULONG(world);
  165.         len -= 8;
  166.         if (strcmp(name, "INFO")==0) process_INFO(size, world);
  167.         else
  168.         if (strcmp(name, "OBJ ")==0) process_OBJ(size, world);
  169.         else {
  170.             if (verbose_flag) output_warning(world, "", name, size);
  171.             else {
  172.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  173.             }
  174.         }
  175.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  176.         len -= size;
  177.     }
  178.  
  179. /* All done. */
  180.     return(world);
  181. }
  182.  
  183. static void process_INFO(len, world)
  184. register ULONG len;
  185. WORLD *world;
  186. {
  187.     register INFO *info;
  188.     register ULONG i, size;
  189.     char name[5];
  190.  
  191.     if (world->info) {
  192.         fputs("ERROR: More than one INFO chunk!\n", stderr); exit(-1); }
  193.     if (!(info = world->info = (INFO*)malloc(sizeof(INFO)))) { OUT_MEM("INFO"); }
  194.     bzero((char*)world->info, sizeof(INFO));
  195.  
  196.     if (verbose_flag>1) fprintf(stderr, "INFO chunk.\n");
  197.     while (len>0) {
  198.         get_name(name, 4, world);
  199.         size = get_ULONG(world);
  200.         len -= 8;
  201.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  202.         if (strcmp(name, "BRSH")==0) {
  203.             i = get_UWORD(world);
  204.             if (i<0 || i>7) { i=0; fputs("BRSH error.\n", stderr); }
  205.             get_name(info->brsh[i], 80, world);
  206.         } else
  207.         if (strcmp(name, "STNC")==0) {
  208.             i = get_UWORD(world);
  209.             if (i<0 || i>7) { i=0; fputs("STNC error.\n", stderr); }
  210.             get_name(info->stnc[i], 80, world);
  211.         } else
  212.         if (strcmp(name, "TXTR")==0) {
  213.             i = get_UWORD(world);
  214.             if (i<0 || i>7) { i=0; fputs("TXTR error.\n", stderr); }
  215.             get_name(info->txtr[i], 80, world);
  216.         } else
  217.         if (strcmp(name, "OBSV")==0) {
  218.             if (!info->obsv) info->obsv=(OBSV*)malloc(sizeof(OBSV));
  219.             if (!info->obsv) { OUT_MEM("OBSV"); }
  220.             stuff_XYZ(&info->obsv->came, world);
  221.             stuff_XYZ(&info->obsv->rota, world);
  222.             info->obsv->foca = get_FRACT(world);
  223.         } else
  224.         if (strcmp(name, "OTRK")==0) {
  225.             get_name(info->otrk, 18, world);
  226.         } else
  227.         if (strcmp(name, "OSTR")==0) {
  228.             if (!info->ostr) info->ostr=(STRY*)malloc(sizeof(STRY));
  229.             if (!info->ostr) { OUT_MEM("OSTR"); }
  230.             get_name(info->ostr->path, 18, world);
  231.             stuff_XYZ(&info->ostr->tran, world);
  232.             stuff_XYZ(&info->ostr->rota, world);
  233.             stuff_XYZ(&info->ostr->scal, world);
  234.             info->ostr->info = get_UWORD(world);
  235.         } else
  236.         if (strcmp(name, "FADE")==0) {
  237.             if (!info->fade) info->fade=(FADE*)malloc(sizeof(FADE));
  238.             if (!info->fade) { OUT_MEM("FADE"); }
  239.             info->fade->at = get_FRACT(world);
  240.             info->fade->by = get_FRACT(world);
  241.             fgetc(world->inp);        /* Skip a byte */
  242.             stuff_RGB(&info->fade->to, world);
  243.         } else
  244.         if (strcmp(name, "SKYC")==0) {
  245.             if (!info->skyc) info->skyc=(SKYC*)malloc(sizeof(SKYC));
  246.             if (!info->skyc) { OUT_MEM("SKYC"); }
  247.             fgetc(world->inp);        /* Skip a byte */
  248.             stuff_RGB(&info->skyc->hori, world);
  249.             fgetc(world->inp);        /* Skip a byte */
  250.             stuff_RGB(&info->skyc->zeni, world);
  251.         } else
  252.         if (strcmp(name, "AMBI")==0) {
  253.             if (!info->ambi) info->ambi=(RGB_st*)malloc(sizeof(RGB_st));
  254.             if (!info->ambi) { OUT_MEM("AMBI"); }
  255.             fgetc(world->inp);        /* Skip a byte */
  256.             stuff_RGB(info->ambi, world);
  257.         } else
  258.         if (strcmp(name, "GLB0")==0) {
  259.             if (!info->glb0) info->glb0=(BYTE*)malloc(8*sizeof(BYTE));
  260.             if (!info->glb0) { OUT_MEM("GLB0"); }
  261.             for (i=0; i<8; i++)
  262.                 info->glb0[i] = get_UBYTE(world);
  263.         } else {
  264.             if (verbose_flag) output_warning(world, "INFO ", name, size);
  265.             else {
  266.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  267.             }
  268.         }
  269.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  270.         len -= size;
  271.     }
  272. }
  273.  
  274. static void process_OBJ(len, world)
  275. register ULONG len;
  276. WORLD *world;
  277. {
  278.     register ULONG i, size;
  279.     register OBJECT *p;
  280.     char name[5];
  281.     int depth=0;
  282.  
  283.     if (verbose_flag>1) fprintf(stderr, "OBJ chunk.\n");
  284.     while (len>0) {
  285.         get_name(name, 4, world);
  286.         size = get_ULONG(world);
  287.         len -= 8;
  288.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  289.         if (strcmp(name, "EXTR")==0) {
  290.             p = process_EXTR(size, create_object(), world);
  291.             if (world->curobj) {
  292.                 world->curobj->next = p;
  293.                 p->parent = world->curobj->parent;
  294.             } else {
  295.                 world->object = p;
  296.                 p->parent = 0;
  297.             }
  298.             world->curobj = p;
  299.         } else if (strcmp(name, "DESC")==0) {
  300.             p = create_object();
  301.             if (world->num_DESC > world->num_TOBJ+depth) {  /* This is a child */
  302.                 depth++;    /* Down one in the hierarchy */
  303.                 world->curobj->child = p;
  304.                 p->parent = world->curobj;
  305.             } else {
  306.                 if (world->curobj) {
  307.                     world->curobj->next = p;
  308.                     p->parent = world->curobj->parent;
  309.                 } else {
  310.                     world->object = p;
  311.                     p->parent = 0;
  312.                 }
  313.             }
  314.             world->curobj = p;
  315.             process_DESC(size, &p->desc, world);
  316.         } else if (strcmp(name, "TOBJ")==0) {
  317.             world->num_TOBJ++;
  318.             if (world->num_TOBJ > world->num_DESC) {
  319.                 fprintf(stderr, "Warning: TOBJ without DESC.  Ignored.\n");
  320.             }
  321.             if (world->num_TOBJ+depth > world->num_DESC) {  /* Up a level */
  322.                 depth--;
  323.                 world->curobj=world->curobj->parent;
  324.             }
  325.         } else {
  326.             if (verbose_flag) output_warning(world, "OBJ ", name, size);
  327.             else {
  328.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  329.             }
  330.         }
  331.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  332.         len -= size;
  333.     }
  334. }
  335.  
  336. static OBJECT *process_EXTR(len, obj, world)
  337. register ULONG len;
  338. OBJECT *obj;
  339. WORLD *world;
  340. {
  341.     register ULONG i, size;
  342.     register EXTR *extr;
  343.     register OBJECT *p;
  344.     char name[5];
  345.     MTRX *mtrx;
  346.     WORLD *new;
  347.     FILE *newinp;
  348.  
  349.     if (!(extr = obj->extr = (EXTR*)malloc(sizeof(EXTR))))
  350.         { OUT_MEM("EXTR"); }
  351.     bzero((char*)extr, sizeof(EXTR));
  352.     mtrx = &extr->mtrx;
  353.     /* Initialize structure */
  354.     mtrx->tran.x  = mtrx->tran.y  = mtrx->tran.z  = 0.0;
  355.     mtrx->scal.x  = mtrx->scal.y  = mtrx->scal.z  = 1.0;
  356.     mtrx->rota1.y = mtrx->rota1.z = 0.0;
  357.     mtrx->rota2.x = mtrx->rota2.z = 0.0;
  358.     mtrx->rota3.x = mtrx->rota3.y = 0.0;
  359.     mtrx->rota1.x = mtrx->rota2.y = mtrx->rota3.z = 1.0;
  360.  
  361.     if (verbose_flag>1) fprintf(stderr, "EXTR chunk.\n");
  362.     while (len>0) {
  363.         get_name(name, 4, world);
  364.         size = get_ULONG(world);
  365.         len -= 8;
  366.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  367.         if (strcmp(name, "MTRX")==0) {
  368.             stuff_XYZ(&mtrx->tran, world);
  369.             stuff_XYZ(&mtrx->scal, world);
  370.             stuff_XYZ(&mtrx->rota1, world);
  371.             stuff_XYZ(&mtrx->rota2, world);
  372.             stuff_XYZ(&mtrx->rota3, world);
  373.         } else
  374.         if (strcmp(name, "LOAD")==0) {
  375.             get_name(extr->filename, 80, world);
  376.         } else {
  377.             if (verbose_flag) output_warning(world, "EXTR ", name, size);
  378.             else {
  379.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  380.             }
  381.         }
  382.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  383.         len -= size;
  384.     }
  385.     /* Now, load in the external object */
  386.     if (!(newinp=fopen(extr->filename, "r"))) {
  387.         fprintf(stderr, "Can't load in EXTR object: '%s'... ignored.\n",
  388.             extr->filename);
  389.         return(obj);
  390.     }
  391.     new = read_World(newinp);
  392.     fclose(newinp);
  393.     /* scale, rotate, and translate new object hierarchy */
  394.     for (p=new->object; p; p=p->next)
  395.         move_extr(p, mtrx);
  396.     /* Free up unused memory */
  397.     free((char*)obj->extr);
  398.     free((char*)obj);
  399.     obj = new->object;
  400.     free((char*)new);
  401.     return(obj);
  402. }
  403.  
  404. static UBYTE defclst[3], defrlst[3], deftlst[3], defspc1[3];
  405.  
  406. static void malloc_arrays(i, desc)
  407. register int i;
  408. register DESC *desc;
  409. {
  410.     if (!desc->fcount) {
  411.         desc->fcount = i;
  412. if (!(desc->face=(UWORD*)malloc(3*desc->fcount*sizeof(UWORD))))OUT_MEM((char*)0);
  413. if (!(desc->clst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  414. if (!(desc->rlst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  415. if (!(desc->tlst=(UBYTE*)malloc(3*desc->fcount*sizeof(UBYTE))))OUT_MEM((char*)0);
  416.         /* Initialize arrays */
  417.         for (i=0; i<3*desc->fcount; i+=3) {
  418.             desc->face[i]   = desc->face[i+1] = desc->face[i+2] = 0;
  419.             desc->clst[i]   = defclst[0];
  420.             desc->clst[i+1] = defclst[1];
  421.             desc->clst[i+2] = defclst[2];
  422.             desc->rlst[i]   = defrlst[0];
  423.             desc->rlst[i+1] = defrlst[1];
  424.             desc->rlst[i+2] = defrlst[2];
  425.             desc->tlst[i]   = deftlst[0];
  426.             desc->tlst[i+1] = deftlst[1];
  427.             desc->tlst[i+2] = deftlst[2];
  428.         }
  429.     } else if (i != desc->fcount) {
  430.         fprintf(stderr, "ERROR: FACE and [C|R|T]LST 'Count' values inconsistant.\n");
  431.         OUT_MEM((char*)0);
  432.     }
  433. }
  434.  
  435. static void process_DESC(len, orig, world)
  436. register ULONG len;
  437. DESC **orig;
  438. WORLD *world;
  439. {
  440.     register ULONG size;
  441.     register DESC *desc;
  442.     register int i, j;
  443.     FGRP *fgrp;
  444.     char name[5];
  445.  
  446.     if (!(desc = *orig = (DESC*)malloc(sizeof(DESC))))
  447.         { OUT_MEM("DESC"); }
  448.     bzero((char*)desc, sizeof(DESC));
  449.  
  450.     /* Set up defaults: */
  451.     defclst[0] = defclst[1] = defclst[2] = 240; /* TS default */
  452.     defrlst[0] = defrlst[1] = defrlst[2] = 0;
  453.     deftlst[0] = deftlst[1] = deftlst[2] = 0;
  454.     defspc1[0] = defspc1[1] = defspc1[2] = 0;
  455.  
  456.     world->num_DESC++;
  457.  
  458.     if (verbose_flag>1) fprintf(stderr, "DESC chunk.\n");
  459.     while (len>0) {
  460.         get_name(name, 4, world);
  461.         size = get_ULONG(world);
  462.         len -= 8;
  463.         if (verbose_flag>1) fprintf(stderr, "%s chunk.\n", name);
  464.         if (strcmp(name, "NAME")==0) {
  465.             get_name(desc->name, 18, world);
  466.         } else
  467.         if (strcmp(name, "SHAP")==0) {
  468.             if (!desc->shap) {
  469.                 if (!(desc->shap=(WORD*)malloc(2*sizeof(WORD))))
  470.                     { OUT_MEM("SHAP"); }
  471.                 desc->shap[0] = 2;  /* TS defaults */
  472.                 desc->shap[1] = 0;
  473.             }
  474.             desc->shap[0] = get_UWORD(world);
  475.             desc->shap[1] = get_UWORD(world);
  476.         } else
  477.         if (strcmp(name, "POSI")==0) {
  478.             if (!desc->posi) {
  479.                 if (!(desc->posi=(XYZ_st*)malloc(sizeof(XYZ_st))))
  480.                     { OUT_MEM("POSI"); }
  481.             }
  482.             stuff_XYZ(desc->posi, world);
  483.         } else
  484.         if (strcmp(name, "AXIS")==0) {
  485.             if (!desc->axis) {
  486.                 if (!(desc->axis=(AXIS*)malloc(sizeof(AXIS))))
  487.                     { OUT_MEM("AXIS"); }
  488.                 bzero((char*)desc->axis, sizeof(AXIS));
  489.                 desc->axis->xaxi.x = 1;
  490.                 desc->axis->yaxi.y = 1;
  491.                 desc->axis->zaxi.z = 1;
  492.             }
  493.             stuff_XYZ(&desc->axis->xaxi, world);
  494.             stuff_XYZ(&desc->axis->yaxi, world);
  495.             stuff_XYZ(&desc->axis->zaxi, world);
  496.         } else
  497.         if (strcmp(name, "SIZE")==0) {
  498.             if (!desc->size) {
  499.                 if (!(desc->size=(XYZ_st*)malloc(sizeof(XYZ_st))))
  500.                     { OUT_MEM("SIZE"); }
  501.             }
  502.             stuff_XYZ(desc->size, world);
  503.         } else
  504.         if (strcmp(name, "PNTS")==0) {
  505.             i = desc->pcount = get_UWORD(world);    /* Number of points */
  506.             if (!(desc->pnts = (XYZ_st*)malloc(desc->pcount*sizeof(XYZ_st))))
  507.                 OUT_MEM("PNTS");
  508.             for (j=0; j<i; j++)
  509.                 { stuff_XYZ(&desc->pnts[j], world); }
  510.         } else
  511.         if (strcmp(name, "EDGE")==0) {
  512.             i = desc->ecount = get_UWORD(world);    /* Number of edges */
  513.             if (!(desc->edge = (UWORD*)malloc(2*desc->ecount*sizeof(UWORD))))
  514.                 OUT_MEM("EDGE");
  515.             for (j=0; j<2*i; j++)
  516.                 { desc->edge[j] = get_UWORD(world); }
  517.         } else
  518.         if (strcmp(name, "EFLG")==0) {
  519.             if (!(desc->eflg = (EFLG*)malloc(sizeof(EFLG))))
  520.                 OUT_MEM("EFLG");
  521.             i = desc->eflg->num = get_UWORD(world);    /* Number of edge flags */
  522.             if (!(desc->eflg->eflg=(UBYTE*)malloc(desc->eflg->num*sizeof(UBYTE))))
  523.                 OUT_MEM("EFLG");
  524.             for (j=0; j<i; j++)
  525.                 { desc->eflg->eflg[j] = get_UBYTE(world); }
  526.         } else
  527.         if (strcmp(name, "FACE")==0) {
  528.             i = get_UWORD(world);                /* Number of faces */
  529.             malloc_arrays(i, desc);
  530.             for (j=0; j<i; j++) {
  531.                 desc->face[3*j]   = get_UWORD(world);
  532.                 desc->face[3*j+1] = get_UWORD(world);
  533.                 desc->face[3*j+2] = get_UWORD(world);
  534.             }
  535.         } else
  536.         if (strcmp(name, "FGRP")==0) {
  537.             if (!(fgrp = (FGRP*)malloc(sizeof(FGRP))))
  538.                 OUT_MEM("FGRP");
  539.             i = fgrp->num = get_UWORD(world);    /* Number of faces in group */
  540.             if (!(fgrp->face = (UWORD*)malloc(i*sizeof(UWORD))))
  541.                 OUT_MEM("FGRP");
  542.             get_name(fgrp->name, 18, world);
  543.             for (j=0; j<i; j++)
  544.                 fgrp->face[j] = get_UWORD(world);
  545.             /* Link this new FGRP into list */
  546.             fgrp->next = desc->fgrp;
  547.             desc->fgrp = fgrp;
  548.         } else
  549.         if (strcmp(name, "COLR")==0) {
  550.             if (!desc->colr) {
  551.                 if (!(desc->colr = (RGB_st*)malloc(sizeof(RGB_st))))
  552.                     { OUT_MEM("COLR"); }
  553.             }
  554.             fgetc(world->inp);            /* Must be zero */
  555.             stuff_RGB((RGB_st*)&defclst[0], world);
  556.             desc->colr->r = defclst[0];
  557.             desc->colr->g = defclst[1];
  558.             desc->colr->b = defclst[2];
  559.         } else
  560.         if (strcmp(name, "REFL")==0) {
  561.             if (!desc->refl) {
  562.                 if (!(desc->refl = (RGB_st*)malloc(sizeof(RGB_st))))
  563.                     { OUT_MEM("REFL"); }
  564.             }
  565.             fgetc(world->inp);            /* Must be zero */
  566.             stuff_RGB((RGB_st*)&defrlst[0], world);
  567.             desc->refl->r = defrlst[0];
  568.             desc->refl->g = defrlst[1];
  569.             desc->refl->b = defrlst[2];
  570.         } else
  571.         if (strcmp(name, "TRAN")==0) {
  572.             if (!desc->tran) {
  573.                 if (!(desc->tran = (RGB_st*)malloc(sizeof(RGB_st))))
  574.                     { OUT_MEM("TRAN"); }
  575.             }
  576.             fgetc(world->inp);            /* Must be zero */
  577.             stuff_RGB((RGB_st*)&deftlst[0], world);
  578.             desc->tran->r = deftlst[0];
  579.             desc->tran->g = deftlst[1];
  580.             desc->tran->b = deftlst[2];
  581.         } else
  582.         if (strcmp(name, "SPC1")==0) {
  583.             if (!desc->spc1) {
  584.                 if (!(desc->spc1 = (RGB_st*)malloc(sizeof(RGB_st))))
  585.                     { OUT_MEM("SPC1"); }
  586.             }
  587.             fgetc(world->inp);            /* Must be zero */
  588.             stuff_RGB((RGB_st*)&defspc1[0], world);
  589.             desc->spc1->r = defspc1[0];
  590.             desc->spc1->g = defspc1[1];
  591.             desc->spc1->b = defspc1[2];
  592.         } else
  593.         if (strcmp(name, "CLST")==0) {
  594.             i = get_UWORD(world);        /* Number of faces */
  595.             malloc_arrays(i, desc);
  596.             for (j=0; j<i; j++)
  597.                 { stuff_RGB((RGB_st*)&desc->clst[3*j], world); }
  598.         } else
  599.         if (strcmp(name, "RLST")==0) {
  600.             i = get_UWORD(world);        /* Number of faces */
  601.             malloc_arrays(i, desc);
  602.             for (j=0; j<i; j++)
  603.                 { stuff_RGB((RGB_st*)&desc->rlst[3*j], world); }
  604.         } else
  605.         if (strcmp(name, "TLST")==0) {
  606.             i = get_UWORD(world);        /* Number of faces */
  607.             malloc_arrays(i, desc);
  608.             for (j=0; j<i; j++)
  609.                 { stuff_RGB((RGB_st*)&desc->tlst[3*j], world); }
  610.         } else
  611.         if (strcmp(name, "TPAR")==0) {
  612.             if (!desc->tpar) {
  613.                 if (!(desc->tpar=(double*)malloc(16*sizeof(double))))
  614.                     { OUT_MEM("TPAR"); }
  615.                 bzero((char*)desc->tpar, 16*sizeof(double));
  616.             }
  617.             for (i=0; i<16; i++)
  618.                 desc->tpar[i] = get_FRACT(world);
  619.         } else
  620.         if (strcmp(name, "SURF")==0) {
  621.             if (!desc->surf) {
  622.                 if (!(desc->surf=(UBYTE*)malloc(5*sizeof(UBYTE))))
  623.                     { OUT_MEM("SURF"); }
  624.                 bzero((char*)desc->surf, 5*sizeof(UBYTE));
  625.             }
  626.             for (i=0; i<5; i++)
  627.                 desc->surf[i] = get_BYTE(world);
  628.         } else
  629.         if (strcmp(name, "MTTR")==0) {
  630.             if (!desc->mttr) {
  631.                 if (!(desc->mttr=(MTTR*)malloc(sizeof(MTTR))))
  632.                     { OUT_MEM("MTTR"); }
  633.                 bzero((char*)desc->mttr, sizeof(MTTR));
  634.             }
  635.             desc->mttr->type = get_UBYTE(world);
  636.             desc->mttr->indx = (get_UBYTE(world)/100.0)+1.0;
  637.         } else
  638.         if (strcmp(name, "SPEC")==0) {
  639.             if (!desc->spec) {
  640.                 if (!(desc->spec=(UBYTE*)malloc(2*sizeof(UBYTE))))
  641.                     { OUT_MEM("SPEC"); }
  642.                 bzero((char*)desc->spec, 2*sizeof(UBYTE));
  643.             }
  644.             desc->spec[0] = get_UBYTE(world);
  645.             desc->spec[1] = get_UBYTE(world);
  646.         } else
  647.         if (strcmp(name, "PRP0")==0) {
  648.             if (!desc->prp0) {
  649.                 if (!(desc->prp0=(UBYTE*)malloc(6*sizeof(UBYTE))))
  650.                     { OUT_MEM("PRP0"); }
  651.                 bzero((char*)desc->prp0, 6*sizeof(UBYTE));
  652.             }
  653.             for (i=0; i<6; i++)
  654.                 desc->prp0[i] = get_UBYTE(world);
  655.         } else
  656.         if (strcmp(name, "PRP1")==0) {
  657.             if (!desc->prp1) {
  658.                 if (!(desc->prp1=(UBYTE*)malloc(8*sizeof(UBYTE))))
  659.                     { OUT_MEM("PRP1"); }
  660.                 bzero((char*)desc->prp1, 8*sizeof(UBYTE));
  661.             }
  662.             for (i=0; i<8; i++)
  663.                 desc->prp1[i] = get_UBYTE(world);
  664.         } else
  665.         if (strcmp(name, "INTS")==0) {
  666.             if (!desc->ints) {
  667.                 if (!(desc->ints=(double*)malloc(sizeof(double))))
  668.                     { OUT_MEM("INTS"); }
  669.             }
  670.             *desc->ints = get_FRACT(world);
  671.         } else
  672.         if (strcmp(name, "INT1")==0) {
  673.             if (!desc->int1) desc->int1=(XYZ_st*)malloc(sizeof(XYZ_st));
  674.             if (!desc->int1) { OUT_MEM("INT1"); }
  675.             stuff_XYZ(desc->int1, world);
  676.         } else
  677.         if (strcmp(name, "STRY")==0) {
  678.             get_name(desc->stry->path, 18, world);
  679.             stuff_XYZ(&desc->stry->tran, world);
  680.             stuff_XYZ(&desc->stry->rota, world);
  681.             stuff_XYZ(&desc->stry->scal, world);
  682.             desc->stry->info = get_UWORD(world);
  683.         } else {
  684.             if (verbose_flag) output_warning(world, "DESC ", name, size);
  685.             else {
  686.                 for (i=size; i--; ) fgetc(world->inp);    /* Skip this section */
  687.             }
  688.         }
  689.         if (size&1) { fgetc(world->inp); len--; }    /* Skip odd byte */
  690.         len -= size;
  691.     }
  692. }
  693.  
  694.